unit SmallStruct.Database.TSSDBXDatabaseDriver;

interface

uses Classes,
  SqlExpr,
  DBXpress,
  SmallStruct.Core,
  SmallStruct.Database,
  SmallStruct.Database.TSSDatabaseDriver;

const
  SS_DBX_DRIVER_NAME = 'DRIVERNAME';
  SS_DBX_DRIVER_FUNC = 'DRIVER_FUNC';
  SS_DBX_LABRARY_NAME = 'LABRARY_NAME';
  SS_DBX_VENDOR_LIB = 'VENDOR_LIB';
  SS_DBX_DATABASE = 'DATABASE';
  SS_DBX_USER_NAME = 'USER_NAME';
  SS_DBX_PASSOWRD = 'PASWORD';
  SS_DBX_BLOB_SIZE = 'BLOBSIZE';
  SS_DBX_ERROR_RESOURCE_FILE = 'ERRORRESOURCEFILE';
  SS_DBX_LOCALE_CODE = 'LOCALECODE';
  SS_DBX_ORACLE_TRANS_ISOLATION = 'ORACLE TRANSISOLATION';
  SS_DBX_ROWSET_SIZE = 'ROWSETSIZE';
  SS_DBX_OS_AUTHENTICATION = 'OS AUTHENTICATION';
  SS_DBX_MULTIPLE_TRANSACTION = 'MULTIPLE TRANSACTION';
  SS_DBX_TRIM_CHAR = 'TRIM CHAR';

type
  ISSDBXDatabaseDriver = interface(ISSDatabaseDriver)
    ['{CD929D2C-C8B4-4DE6-808A-55FCEAD1D5C4}']
    function GetConnection: TSQLConnection;
  end;

  TSSDBXDatabaseDriver = class(TSSDatabaseDriver, ISSDBXDatabaseDriver)
  private
    _Connection: TSQLConnection;
    _TransactionDesc: TTransactionDesc;
  protected
    function GetConnection: TSQLConnection;
  public
    function ExecuteProcedure(const ProcedureName: string; Parameters: Variant): Integer; override;
    function ExecuteSQL(const SQL: string): Integer; override;
    function Query(const SQL: string): ISSDataSet; override;
    procedure CommitTransaction; override;
    procedure Conntect; override;
    procedure Deconnect; override;
    procedure RollbackTransaction; override;
    procedure StartTransaction; override;
  public
    procedure InitObject; override;
  public
    constructor Create(AOwner: TComponent); override;
  end;

implementation

uses Variants,
  Provider,
  SmallStruct.Configuration,
  SmallStruct.Database.TSSDataSet;

{ TSSDBXDatabaseDriver }

procedure TSSDBXDatabaseDriver.CommitTransaction;
begin
  _Connection.Commit(_TransactionDesc);
end;

procedure TSSDBXDatabaseDriver.Conntect;
begin
  _Connection.Open;
end;

constructor TSSDBXDatabaseDriver.Create(AOwner: TComponent);
begin
  inherited;
  _Connection := TSQLConnection.Create(Self);
  _Connection.LoginPrompt := False;
  _Connection.KeepConnection := False;
end;

procedure TSSDBXDatabaseDriver.Deconnect;
begin
  _Connection.Close;
end;

function TSSDBXDatabaseDriver.ExecuteProcedure(const ProcedureName: string; Parameters: Variant): Integer;
var
  SP: TSQLStoredProc;
  Index: Integer;
  ParamList: TList;
begin
  SP := TSQLStoredProc.Create(Self);
  SP.SQLConnection := _Connection;
  ParamList := TList.Create;
  try
    _Connection.GetProcedureParams(ProcedureName, ParamList);

    for Index := 0 to ParamList.Count - 1 do
      SP.Params.CreateParam((PSPParamDesc(ParamList.Items[Index]))^.iDataType, (PSPParamDesc(ParamList.Items[Index]))^.szName, (PSPParamDesc(ParamList.Items[Index]))^.iArgType);

    SP.StoredProcName := ProcedureName;

    for Index := 0 to VarArrayHighBound(Parameters, 1) do
      SP.Params[0].Value := Parameters[0];

    Result := SP.ExecProc;
  finally
    SP.Free;
    FreeProcParams(ParamList);
  end;
end;

function TSSDBXDatabaseDriver.ExecuteSQL(const SQL: string): Integer;
begin
  Result := _Connection.ExecuteDirect(SQL);
end;

function TSSDBXDatabaseDriver.GetConnection: TSQLConnection;
begin
  Result := _Connection;
end;

procedure TSSDBXDatabaseDriver.InitObject;
var
  DatabaseConfiguration: ISSDatabaseConnectionConfiguration;
begin
  inherited;
  DatabaseConfiguration := GetContext.GetConfiguration as ISSDatabaseConnectionConfiguration;
  try
    _Connection.DriverName := DatabaseConfiguration.GetConnectionString.Values[SS_DBX_DRIVER_NAME];
    _Connection.GetDriverFunc := DatabaseConfiguration.GetConnectionString.Values[SS_DBX_DRIVER_FUNC];
    _Connection.LibraryName := DatabaseConfiguration.GetConnectionString.Values[SS_DBX_LABRARY_NAME];
    _Connection.VendorLib := DatabaseConfiguration.GetConnectionString.Values[SS_DBX_VENDOR_LIB];
    _Connection.Params.AddStrings(DatabaseConfiguration.GetConnectionString);
  finally
    DatabaseConfiguration := nil;
  end;
end;

function TSSDBXDatabaseDriver.Query(const SQL: string): ISSDataSet;
var
  SQLQuery: TSQLQuery;
  DataSetProvider: TDataSetProvider;
  DataSet: TSSDataSet;
begin
  SQLQuery := TSQLQuery.Create(Self);
  DataSetProvider := TDataSetProvider.Create(Self);

  try
    SQLQuery.SQLConnection := _Connection;
    DataSetProvider.DataSet := SQLQuery;

    SQLQuery.SQL.Text := SQL;
    SQLQuery.Open;

    DataSet := TSSDataSet.Create(nil);
    DataSet.InitDataSet(DataSetProvider.Data);

    Result := DataSet;
  finally
    SQLQuery.Free;
    DataSetProvider.Free;
  end;
end;

procedure TSSDBXDatabaseDriver.RollbackTransaction;
begin
  _Connection.Rollback(_TransactionDesc);
end;

procedure TSSDBXDatabaseDriver.StartTransaction;
begin
  _Connection.StartTransaction(_TransactionDesc);
end;

end.
